上一篇做完了 Government 與 Host 的功能頁面,還將共同功能抽離出來做成 ComponentBase ,使我們開發更順暢,所以今天來完成教育單位與企業單位的功能吧
將新增學歷、新增修課證明與新增證照個別設計成元件(Component),一樣會使用 Tabset 的形式來呈現,有些基本的配置這邊就不會再說明,如:在 Module 裡引入 FormsModule 等操作。
透過 AngularCLI 產生元件:
ng g c modules/main/school/components/education/school-education-add --flat
在新增學歷的時候會需要設置目前的就學狀態,所以我們先設計列舉在 types 資料夾的 form.ts
中:
export enum EducationStatus {
undergraduate,
learning,
graduate
}
好了之後我們就來設計 school-education-add.component.ts
:
import { Component, Injector } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { take } from 'rxjs/operators';
import { ComponentBase } from 'src/app/base/component.base';
import { EducationStatus } from 'src/app/types';
@Component({
selector: 'app-school-education-add',
templateUrl: './school-education-add.component.html',
styleUrls: ['./school-education-add.component.scss']
})
export class SchoolEducationAddComponent extends ComponentBase {
public educationForm: FormGroup;
constructor(
private injector: Injector,
private formBuilder: FormBuilder
) {
super(injector);
this.educationForm = this.formBuilder.group({
contract: ['', [Validators.required, this.addressValidator]],
major: ['', [Validators.required]],
status: [EducationStatus.undergraduate, [Validators.required]]
});
}
public addEducation(data: any): void {
this.isPending = true;
this.setFormDisabled(this.educationForm);
const resume = this.providerSvc.getResume(data.contract);
this.providerSvc.executeMethod(
resume.methods.setEducation(data.status, data.major)
.send({ from: this.providerSvc.defaultAccount })
).pipe(
take(1)
).subscribe(
receipt => {
this.transactionConfirmed();
this.educationForm.reset();
this.setFormDisabled(this.educationForm, false);
},
err => {
this.transactionError(err.message);
this.educationForm.reset();
this.setFormDisabled(this.educationForm, false);
}
);
}
}
設計頁面:
<div class="my-3" *ngIf="!isConfirmed && !isError">
<form
[formGroup]="educationForm"
(ngSubmit)="addEducation(educationForm.value)"
>
<div class="form-group">
<label for="contract">履歷位址</label>
<input
type="text"
class="form-control"
id="contract"
placeholder="輸入履歷位址"
[formControlName]="'contract'"
>
</div>
<div class="form-group">
<label for="major">主修科系</label>
<input
type="text"
class="form-control"
id="major"
placeholder="輸入主修科系"
[formControlName]="'major'"
>
</div>
<div class="form-group">
<label for="status">就學狀態</label>
<select class="form-control" id="status" [formControlName]="'status'">
<option [ngValue]="0">畢業</option>
<option [ngValue]="1">在學中</option>
<option [ngValue]="2">肄業</option>
</select>
</div>
<div class="text-right">
<button type="submit" class="btn btn-primary" [disabled]="educationForm.invalid || isPending">新增</button>
</div>
</form>
</div>
<div class="my-3" *ngIf="isConfirmed">
<div class="alert alert-success alert-dismissible fade show" role="alert">
<strong>更新完成</strong>
<button type="button" class="close" (click)="resetConfirmState()">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
<div class="my-3" *ngIf="isError">
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<strong>發生錯誤</strong> {{ errorMessage }}
<button type="button" class="close" (click)="resetErrorState()">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
透過 AngularCLI 產生元件:
ng g c modules/main/school/components/course/school-course-add --flat
設計 school-course-add.component.ts
:
import { Component, Injector } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { ComponentBase } from 'src/app/base/component.base';
import { take } from 'rxjs/operators';
@Component({
selector: 'app-school-course-add',
templateUrl: './school-course-add.component.html',
styleUrls: ['./school-course-add.component.scss']
})
export class SchoolCourseAddComponent extends ComponentBase {
public courseForm: FormGroup;
constructor(
private injector: Injector,
private formBuilder: FormBuilder
) {
super(injector);
this.courseForm = this.formBuilder.group({
contract: ['', [Validators.required, this.addressValidator]],
name: ['', [Validators.required]],
content: ['', [Validators.required]],
comment: ['', [Validators.required]],
grade: ['', [Validators.required, Validators.pattern(/^(?:[1-9]?\d|100)$/)]]
});
}
public addCourse(data: any): void {
this.isPending = true;
this.setFormDisabled(this.courseForm);
const resume = this.providerSvc.getResume(data.contract);
this.providerSvc.executeMethod(
resume.methods.setCourse(data.name, data.content, data.comment, data.grade)
.send({ from: this.providerSvc.defaultAccount })
).pipe(
take(1)
).subscribe(
receipt => {
this.transactionConfirmed();
this.courseForm.reset();
this.setFormDisabled(this.courseForm, false);
},
err => {
this.transactionError();
this.courseForm.reset();
this.setFormDisabled(this.courseForm, false);
}
);
}
}
設計頁面:
<div class="my-3" *ngIf="!isConfirmed && !isError">
<form
[formGroup]="courseForm"
(ngSubmit)="addCourse(courseForm.value)"
>
<div class="form-group">
<label for="contract">履歷位址</label>
<input
type="text"
class="form-control"
id="contract"
placeholder="輸入履歷位址"
[formControlName]="'contract'"
>
</div>
<div class="form-group">
<label for="name">課程名稱</label>
<input
type="text"
class="form-control"
id="name"
placeholder="輸入課程名稱"
[formControlName]="'name'"
>
</div>
<div class="form-group">
<label for="content">課程內容</label>
<textarea
class="form-control"
id="content"
rows="5"
[formControlName]="'content'"
></textarea>
</div>
<div class="form-group">
<label for="grade">成績</label>
<input
type="text"
class="form-control"
id="grade"
placeholder="輸入成績0~100"
[formControlName]="'grade'"
>
</div>
<div class="form-group">
<label for="comment">評論</label>
<textarea
class="form-control"
id="comment"
rows="5"
[formControlName]="'comment'"
></textarea>
</div>
<div class="text-right">
<button type="submit" class="btn btn-primary" [disabled]="courseForm.invalid || isPending">新增</button>
</div>
</form>
</div>
<div class="my-3" *ngIf="isConfirmed">
<div class="alert alert-success alert-dismissible fade show" role="alert">
<strong>更新完成</strong>
<button type="button" class="close" (click)="resetConfirmState()">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
<div class="my-3" *ngIf="isError">
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<strong>發生錯誤</strong> {{ errorMessage }}
<button type="button" class="close" (click)="resetErrorState()">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
透過 AngularCLI 產生元件:
ng g c modules/main/school/components/license/school-license-add --flat
設計 school-license-add.component.ts
:
import { Component, Injector } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { take } from 'rxjs/operators';
import { ComponentBase } from 'src/app/base/component.base';
@Component({
selector: 'app-school-license-add',
templateUrl: './school-license-add.component.html',
styleUrls: ['./school-license-add.component.scss']
})
export class SchoolLicenseAddComponent extends ComponentBase {
public licenseForm: FormGroup;
constructor(
private injector: Injector,
private formBuilder: FormBuilder
) {
super(injector);
this.licenseForm = this.formBuilder.group({
contract: ['', [Validators.required, this.addressValidator]],
name: ['', [Validators.required]],
content: ['', [Validators.required]]
});
}
public addLicense(data: any): void {
const resume = this.providerSvc.getResume(data.contract);
this.providerSvc.executeMethod(
resume.methods.setLicense(data.name, data.content)
.send({ from: this.providerSvc.defaultAccount })
).pipe(
take(1)
).subscribe(
receipt => {
this.transactionConfirmed();
this.licenseForm.reset();
this.setFormDisabled(this.licenseForm, false);
},
err => {
this.transactionError();
this.licenseForm.reset();
this.setFormDisabled(this.licenseForm, false);
}
);
}
}
設計頁面:
<div class="my-3" *ngIf="!isConfirmed && !isError">
<form
[formGroup]="licenseForm"
(ngSubmit)="addLicense(licenseForm.value)"
>
<div class="form-group">
<label for="contract">履歷位址</label>
<input
type="text"
class="form-control"
id="contract"
placeholder="輸入履歷位址"
[formControlName]="'contract'"
>
</div>
<div class="form-group">
<label for="name">證照名稱</label>
<input
type="text"
class="form-control"
id="name"
placeholder="輸入證照名稱"
[formControlName]="'name'"
>
</div>
<div class="form-group">
<label for="content">證照內容</label>
<textarea
class="form-control"
id="content"
rows="5"
[formControlName]="'content'"
></textarea>
</div>
<div class="text-right">
<button type="submit" class="btn btn-primary" [disabled]="licenseForm.invalid || isPending">新增</button>
</div>
</form>
</div>
<div class="my-3" *ngIf="isConfirmed">
<div class="alert alert-success alert-dismissible fade show" role="alert">
<strong>更新完成</strong>
<button type="button" class="close" (click)="resetConfirmState()">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
<div class="my-3" *ngIf="isError">
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<strong>發生錯誤</strong> {{ errorMessage }}
<button type="button" class="close" (click)="resetErrorState()">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
修改 school.component.html
:
<div class="container my-3">
<div class="jumbotron jumbotron-fluid">
<div class="container">
<h1 class="display-4">教育單位專區</h1>
<p class="lead">提供教育單位新增學歷、修課證明以及證照的頁面</p>
</div>
</div>
</div>
<div class="container">
<ngb-tabset>
<ngb-tab title="新增學歷">
<ng-template ngbTabContent>
<app-school-education-add></app-school-education-add>
</ng-template>
</ngb-tab>
<ngb-tab title="新增修課證明">
<ng-template ngbTabContent>
<app-school-course-add></app-school-course-add>
</ng-template>
</ngb-tab>
<ngb-tab title="新增證照">
<ng-template ngbTabContent>
<app-school-license-add></app-school-license-add>
</ng-template>
</ngb-tab>
</ngb-tabset>
</div>
新增學歷頁面:
新增修課證明頁面:
新增證照頁面:
主要會有設置工作經歷與設置離職日的功能,所以一樣拆成兩個元件,並用 Tabset 來顯示成果。
因為我們要使用 BootStrap 的日期選擇器,所以我們在這邊引入 NgbDatepickerModule
:
import { NgModule } from '@angular/core';
import { NgbTabsetModule, NgbDatepickerModule } from '@ng-bootstrap/ng-bootstrap';
@NgModule({
imports: [
NgbTabsetModule,
NgbDatepickerModule
],
exports: [
NgbTabsetModule,
NgbDatepickerModule
]
})
export class BootstrapModule { }
透過 AngularCLI 產生元件:
ng g c modules/main/company/components/experience/company-experience-add --flat
設計 company-experience-add.component.ts
:
mport { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { take } from 'rxjs/operators';
import { ComponentBase } from 'src/app/base/component.base';
@Component({
selector: 'app-company-experience-add',
templateUrl: './company-experience-add.component.html',
styleUrls: ['./company-experience-add.component.scss']
})
export class CompanyExperienceAddComponent extends ComponentBase {
public experienceForm: FormGroup;
constructor(
private injector: Injector,
private formBuilder: FormBuilder
) {
super(injector);
this.experienceForm = this.formBuilder.group({
contract: ['', [Validators.required, this.addressValidator]],
position: ['', [Validators.required]],
startDate: ['', [Validators.required]]
});
}
public addExperience(data: any): void {
data.startDate = new Date(data.startDate.year, data.startDate.month - 1, data.startDate.day).valueOf();
this.isPending = true;
this.setFormDisabled(this.experienceForm);
const resume = this.providerSvc.getResume(data.contract);
this.providerSvc.executeMethod(
resume.methods.setExperience(data.position, data.startDate)
.send({ from: this.providerSvc.defaultAccount })
).pipe(
take(1)
).subscribe(
receipt => {
this.transactionConfirmed();
this.experienceForm.reset();
this.setFormDisabled(this.experienceForm, false);
},
err => {
this.transactionError();
this.experienceForm.reset();
this.setFormDisabled(this.experienceForm, false);
}
);
}
}
設計頁面:
<div class="my-3" *ngIf="!isConfirmed && !isError">
<form
[formGroup]="experienceForm"
(ngSubmit)="addExperience(experienceForm.value)"
>
<div class="form-group">
<label for="contract">履歷位址</label>
<input
type="text"
class="form-control"
id="contract"
placeholder="輸入履歷位址"
[formControlName]="'contract'"
>
</div>
<div class="form-group">
<label for="position">職稱</label>
<input
type="text"
class="form-control"
id="position"
placeholder="輸入職稱"
[formControlName]="'position'"
>
</div>
<div class="form-group">
<label>開工日</label>
<div class="input-group">
<input class="form-control" placeholder="yyyy-mm-dd"
ngbDatepicker #d="ngbDatepicker" [formControlName]="'startDate'">
<div class="input-group-append">
<button class="btn btn-outline-secondary" (click)="d.toggle()" type="button">+</button>
</div>
</div>
</div>
<div class="text-right">
<button type="submit" class="btn btn-primary" [disabled]="experienceForm.invalid || isPending">新增</button>
</div>
</form>
</div>
<div class="my-3" *ngIf="isConfirmed">
<div class="alert alert-success alert-dismissible fade show" role="alert">
<strong>編輯完成</strong>
<button type="button" class="close" (click)="resetConfirmState()">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
<div class="my-3" *ngIf="isError">
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<strong>發生錯誤</strong> {{ errorMessage }}
<button type="button" class="close" (click)="resetErrorState()">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
透過 AngularCLI 產生元件:
ng g c modules/main/company/components/date/company-experience-end --flat
設計company-experience-end.component.ts
:
import { Component, Injector } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { take } from 'rxjs/operators';
import { ComponentBase } from 'src/app/base/component.base';
@Component({
selector: 'app-company-experience-end',
templateUrl: './company-experience-end.component.html',
styleUrls: ['./company-experience-end.component.scss']
})
export class CompanyExperienceEndComponent extends ComponentBase {
public endDateForm: FormGroup;
constructor(
private injector: Injector,
private formBuilder: FormBuilder
) {
super(injector);
this.endDateForm = this.formBuilder.group({
contract: ['', [Validators.required, this.addressValidator]],
endDate: ['', [Validators.required]]
});
}
public setEndDate(data: any): void {
data.endDate = new Date(data.endDate.year, data.endDate.month - 1, data.endDate.day).valueOf();
this.isPending = true;
this.setFormDisabled(this.endDateForm);
const resume = this.providerSvc.getResume(data.contract);
this.providerSvc.executeMethod(
resume.methods.setJobEndDate(data.endDate)
.send({ from: this.providerSvc.defaultAccount })
).pipe(
take(1)
).subscribe(
receipt => {
this.transactionConfirmed();
this.endDateForm.reset();
this.setFormDisabled(this.endDateForm, false);
},
err => {
this.transactionError();
this.endDateForm.reset();
this.setFormDisabled(this.endDateForm, false);
}
);
}
}
設計頁面:
<div class="my-3" *ngIf="!isConfirmed && !isError">
<form
[formGroup]="endDateForm"
(ngSubmit)="setEndDate(endDateForm.value)"
>
<div class="form-group">
<label for="contract">履歷位址</label>
<input
type="text"
class="form-control"
id="contract"
placeholder="輸入履歷位址"
[formControlName]="'contract'"
>
</div>
<div class="form-group">
<label>離職日</label>
<div class="input-group">
<input class="form-control" placeholder="yyyy-mm-dd"
ngbDatepicker #d="ngbDatepicker" [formControlName]="'endDate'">
<div class="input-group-append">
<button class="btn btn-outline-secondary" (click)="d.toggle()" type="button">+</button>
</div>
</div>
</div>
<div class="text-right">
<button type="submit" class="btn btn-primary" [disabled]="endDateForm.invalid || isPending">確定</button>
</div>
</form>
</div>
<div class="my-3" *ngIf="isConfirmed">
<div class="alert alert-success alert-dismissible fade show" role="alert">
<strong>編輯完成</strong>
<button type="button" class="close" (click)="resetConfirmState()">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
<div class="my-3" *ngIf="isError">
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<strong>發生錯誤</strong> {{ errorMessage }}
<button type="button" class="close" (click)="resetErrorState()">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
修改 company.componemnt.ts
:
<div class="container my-3">
<div class="jumbotron jumbotron-fluid">
<div class="container">
<h1 class="display-4">企業單位專區</h1>
<p class="lead">提供企業單位編輯職位與工作期間</p>
</div>
</div>
</div>
<div class="container">
<ngb-tabset>
<ngb-tab title="設置職位">
<ng-template ngbTabContent>
<app-company-experience-add></app-company-experience-add>
</ng-template>
</ngb-tab>
<ngb-tab title="設置離職日">
<ng-template ngbTabContent>
<app-company-experience-end></app-company-experience-end>
</ng-template>
</ngb-tab>
</ngb-tabset>
</div>
設置工作經歷之頁面:
設置離職日之頁面:
與上一篇做的事情差不多,但經過前一篇的特訓(?),相信各位在這一篇已經十分理解設計的思維。今天的內容完成後,基本上該有的操作都有了,接下來就剩下履歷頁面了!
在"設置工作經歷之元件"裏的company-experience-add.component.html的"<button class="btn btn-outline-secondary" (click)="d.toggle()" type="button">+",
請問"(click)="d.toggle()"的d 是什麼?
因為vscode 提示我"Identifier 'd' is not defined. The component declaration, template variable declarations, and element references do not contain such a member",我怎樣解決? Thank you very much.
原來要在app.module.ts 裏加
import { NgbModal, NgbModule } from '@ng-bootstrap/ng-bootstrap';
import:[.., NgbModule],
你好,我的作法是把 BootStrap 另外包裝成 SharedModule,當然不這麼做也是可以的,如果需要的話,可以參考前面這篇:
https://ithelp.ithome.com.tw/articles/10224125